package morpion;

import java.util.ArrayList;

import neurones.Reseau;

abstract class Player {
	protected int color;
	protected ArrayList<Coup> coups;
	protected Reseau r;
	protected int nb_partie = 0;
	protected int nb_vict = 0;
	protected int nb_nul = 0;
	protected int nb_fail = 0;
	
	
	
	public Player(int color, Reseau r){
		this.color=color;
		this.coups=new ArrayList<Coup>();
		this.r = r;
	}
	
	abstract int play(Morpion m);
	

	public int meilleurPos(Morpion m)
	{
		 int result;
		 double max;
		 double tmp;
		
		 max = -1;
		 result = -1;
		
		for(int i = 0; i < 9; i++)
		{
			tmp = heuristique(m, i);
			if (m.get(i) == Morpion.EMPTY && tmp > max) {result = i; max = tmp;}
			else if (m.get(i) == Morpion.EMPTY && tmp == max && Math.random() > 0.5) {result = i; max = tmp;}
		}
		
		return result;
	}
	
	/**
	 * Le pion mis est une int de 0à8 indiquant la position que l'on vient de jouer
	 * @return 1. si on a alligne 3 pions
	 *         0.75 si on a alligne 2 pions et un EMPTY
	 *         0.9 si il y avait deux pions adverse alligne et que l'on pose notre pion
	 */
	private double heuristique(Morpion m, int pion_mis) {
		double count;
		
		//012
		count = 0;
		if(pion_mis == 0 ||pion_mis == 1 || pion_mis == 2)
		{
			if (m.get(0) == Morpion.WHITE) count++;
			else if (m.get(0) == Morpion.BLACK) count -= 0.2;
			if (m.get(1) == Morpion.WHITE) count++;
			else if (m.get(1) == Morpion.BLACK) count -= 0.2;
			if (m.get(2) == Morpion.WHITE) count++;
			else if (m.get(2) == Morpion.BLACK) count -= 0.2;
			
			if (count == 2) return 1;
		}
		
		//345
		count = 0;
		if(pion_mis == 3 ||pion_mis == 4 || pion_mis == 5)
		{
			if (m.get(3) == Morpion.WHITE) count++;
			else if (m.get(3) == Morpion.BLACK) count -= 0.2;
			if (m.get(4) == Morpion.WHITE) count++;
			else if (m.get(4) == Morpion.BLACK) count -= 0.2;
			if (m.get(5) == Morpion.WHITE) count++;
			else if (m.get(5) == Morpion.BLACK) count -= 0.2;
			
			if (count == 2) return 1;
		}
		
		//678
		count = 0;
		if(pion_mis == 6 ||pion_mis == 7 || pion_mis == 8)
		{
			if (m.get(6) == Morpion.WHITE) count++;
			else if (m.get(6) == Morpion.BLACK) count -= 0.2;
			if (m.get(7) == Morpion.WHITE) count++;
			else if (m.get(7) == Morpion.BLACK) count -= 0.2;
			if (m.get(8) == Morpion.WHITE) count++;
			else if (m.get(8) == Morpion.BLACK) count -= 0.2;
			
			if (count == 2) return 1;
		}
		//036
		count = 0;
		if(pion_mis == 0 ||pion_mis == 3 || pion_mis == 6)
		{
			if (m.get(0) == Morpion.WHITE) count++;
			else if (m.get(0) == Morpion.BLACK) count -= 0.2;
			if (m.get(3) == Morpion.WHITE) count++;
			else if (m.get(3) == Morpion.BLACK) count -= 0.2;
			if (m.get(6) == Morpion.WHITE) count++;
			else if (m.get(6) == Morpion.BLACK) count -= 0.2;
			
			if (count == 2) return 1;
		}
		//147
		count = 0;
		if(pion_mis == 1 ||pion_mis == 4 || pion_mis == 7)
		{
			if (m.get(1) == Morpion.WHITE) count++;
			else if (m.get(1) == Morpion.BLACK) count -= 0.2;
			if (m.get(4) == Morpion.WHITE) count++;
			else if (m.get(4) == Morpion.BLACK) count -= 0.2;
			if (m.get(7) == Morpion.WHITE) count++;
			else if (m.get(7) == Morpion.BLACK) count -= 0.2;
			
			if (count == 2) return 1;
		}
		//258
		count = 0;
		if(pion_mis == 2 ||pion_mis == 5 || pion_mis == 8)
		{
			if (m.get(2) == Morpion.WHITE) count++;
			else if (m.get(2) == Morpion.BLACK) count -= 0.2;
			if (m.get(5) == Morpion.WHITE) count++;
			else if (m.get(5) == Morpion.BLACK) count -= 0.2;
			if (m.get(8) == Morpion.WHITE) count++;
			else if (m.get(8) == Morpion.BLACK) count -= 0.2;
			
			if (count == 2) return 1;
		}
		//048
		count = 0;
		if(pion_mis == 0 ||pion_mis == 4 || pion_mis == 8)
		{
			if (m.get(0) == Morpion.WHITE) count++;
			else if (m.get(0) == Morpion.BLACK) count -= 0.2;
			if (m.get(4) == Morpion.WHITE) count++;
			else if (m.get(4) == Morpion.BLACK) count -= 0.2;
			if (m.get(8) == Morpion.WHITE) count++;
			else if (m.get(8) == Morpion.BLACK) count -= 0.2;
			
			if (count == 2) return 1;
		}
		//246
		count = 0;
		if(pion_mis == 2 ||pion_mis == 4 || pion_mis == 6)
		{
			if (m.get(2) == Morpion.WHITE) count++;
			else if (m.get(2) == Morpion.BLACK) count -= 0.2;
			if (m.get(4) == Morpion.WHITE) count++;
			else if (m.get(4) == Morpion.BLACK) count -= 0.2;
			if (m.get(6) == Morpion.WHITE) count++;
			else if (m.get(6) == Morpion.BLACK) count -= 0.2;
			
			if (count == 2) return 1;
		}
		
		//contre
		//012
		count = 0;
		if(pion_mis == 0 ||pion_mis == 1 || pion_mis == 2)
		{
			if (m.get(0) == Morpion.BLACK) count++;
			if (m.get(1) == Morpion.BLACK) count++;
			if (m.get(2) == Morpion.BLACK) count++;
			
			if (count == 2) return 0.9;
		}
		
		//345
		count = 0;
		if(pion_mis == 3 ||pion_mis == 4 || pion_mis == 5)
		{
			if (m.get(3) == Morpion.BLACK) count++;
			if (m.get(4) == Morpion.BLACK) count++;
			if (m.get(5) == Morpion.BLACK) count++;
			
			if (count == 2) return 0.9;
		}
		
		//678
		count = 0;
		if(pion_mis == 6 ||pion_mis == 7 || pion_mis == 8)
		{
			if (m.get(6) == Morpion.BLACK) count++;
			if (m.get(7) == Morpion.BLACK) count++;
			if (m.get(8) == Morpion.BLACK) count++;
			
			if (count == 2) return 0.9;
		}
		//036
		count = 0;
		if(pion_mis == 0 ||pion_mis == 3 || pion_mis == 6)
		{
			if (m.get(0) == Morpion.BLACK) count++;
			if (m.get(3) == Morpion.BLACK) count++;
			if (m.get(6) == Morpion.BLACK) count++;
			
			if (count == 2) return 0.9;
		}
		//147
		count = 0;
		if(pion_mis == 1 ||pion_mis == 4 || pion_mis == 7)
		{
			if (m.get(1) == Morpion.BLACK) count++;
			if (m.get(4) == Morpion.BLACK) count++;
			if (m.get(7) == Morpion.BLACK) count++;
			
			if (count == 2) return 0.9;
		}
		//258
		count = 0;
		if(pion_mis == 2 ||pion_mis == 5 || pion_mis == 8)
		{
			if (m.get(2) == Morpion.BLACK) count++;
			if (m.get(5) == Morpion.BLACK) count++;
			if (m.get(8) == Morpion.BLACK) count++;
			
			if (count == 2) return 0.9;
		}
		//048
		count = 0;
		if(pion_mis == 0 ||pion_mis == 4 || pion_mis == 8)
		{
			if (m.get(0) == Morpion.BLACK) count++;
			if (m.get(4) == Morpion.BLACK) count++;
			if (m.get(8) == Morpion.BLACK) count++;
			
			if (count == 2) return 0.9;
		}
		//246
		count = 0;
		if(pion_mis == 2 ||pion_mis == 4 || pion_mis == 6)
		{
			if (m.get(2) == Morpion.BLACK) count++;
			if (m.get(4) == Morpion.BLACK) count++;
			if (m.get(6) == Morpion.BLACK) count++;
			
			if (count == 2) return 0.9;
		}
		
		//aligne 2
		//012
		count = 0;
		if(pion_mis == 0 ||pion_mis == 1 || pion_mis == 2)
		{
			if (m.get(0) == Morpion.WHITE) count++;
			else if (m.get(0) == Morpion.BLACK) count -= 0.2;
			if (m.get(1) == Morpion.WHITE) count++;
			else if (m.get(1) == Morpion.BLACK) count -= 0.2;
			if (m.get(2) == Morpion.WHITE) count++;
			else if (m.get(2) == Morpion.BLACK) count -= 0.2;
			
			if (count == 1) return 0.6;
		}
		
		//345
		count = 0;
		if(pion_mis == 3 ||pion_mis == 4 || pion_mis == 5)
		{
			if (m.get(3) == Morpion.WHITE) count++;
			else if (m.get(3) == Morpion.BLACK) count -= 0.2;
			if (m.get(4) == Morpion.WHITE) count++;
			else if (m.get(4) == Morpion.BLACK) count -= 0.2;
			if (m.get(5) == Morpion.WHITE) count++;
			else if (m.get(5) == Morpion.BLACK) count -= 0.2;
			
			if (count == 1) return 0.6;
		}
		
		//678
		count = 0;
		if(pion_mis == 6 ||pion_mis == 7 || pion_mis == 8)
		{
			if (m.get(6) == Morpion.WHITE) count++;
			else if (m.get(6) == Morpion.BLACK) count -= 0.2;
			if (m.get(7) == Morpion.WHITE) count++;
			else if (m.get(7) == Morpion.BLACK) count -= 0.2;
			if (m.get(8) == Morpion.WHITE) count++;
			else if (m.get(8) == Morpion.BLACK) count -= 0.2;
			
			if (count == 1) return 0.6;
		}
		//036
		count = 0;
		if(pion_mis == 0 ||pion_mis == 3 || pion_mis == 6)
		{
			if (m.get(0) == Morpion.WHITE) count++;
			else if (m.get(0) == Morpion.BLACK) count -= 0.2;
			if (m.get(3) == Morpion.WHITE) count++;
			else if (m.get(3) == Morpion.BLACK) count -= 0.2;
			if (m.get(6) == Morpion.WHITE) count++;
			else if (m.get(6) == Morpion.BLACK) count -= 0.2;
			
			if (count == 1) return 0.6;
		}
		//147
		count = 0;
		if(pion_mis == 1 ||pion_mis == 4 || pion_mis == 7)
		{
			if (m.get(1) == Morpion.WHITE) count++;
			else if (m.get(1) == Morpion.BLACK) count -= 0.2;
			if (m.get(4) == Morpion.WHITE) count++;
			else if (m.get(4) == Morpion.BLACK) count -= 0.2;
			if (m.get(7) == Morpion.WHITE) count++;
			else if (m.get(7) == Morpion.BLACK) count -= 0.2;
			
			if (count == 1) return 0.6;
		}
		//258
		count = 0;
		if(pion_mis == 2 ||pion_mis == 5 || pion_mis == 8)
		{
			if (m.get(2) == Morpion.WHITE) count++;
			else if (m.get(2) == Morpion.BLACK) count -= 0.2;
			if (m.get(5) == Morpion.WHITE) count++;
			else if (m.get(5) == Morpion.BLACK) count -= 0.2;
			if (m.get(8) == Morpion.WHITE) count++;
			else if (m.get(8) == Morpion.BLACK) count -= 0.2;
			
			if (count == 1) return 0.6;
		}
		//048
		count = 0;
		if(pion_mis == 0 ||pion_mis == 4 || pion_mis == 8)
		{
			if (m.get(0) == Morpion.WHITE) count++;
			else if (m.get(0) == Morpion.BLACK) count -= 0.2;
			if (m.get(4) == Morpion.WHITE) count++;
			else if (m.get(4) == Morpion.BLACK) count -= 0.2;
			if (m.get(8) == Morpion.WHITE) count++;
			else if (m.get(8) == Morpion.BLACK) count -= 0.2;
			
			if (count == 1) return 0.6;
		}
		//246
		count = 0;
		if(pion_mis == 2 ||pion_mis == 4 || pion_mis == 6)
		{
			if (m.get(2) == Morpion.WHITE) count++;
			else if (m.get(2) == Morpion.BLACK) count -= 0.2;
			if (m.get(4) == Morpion.WHITE) count++;
			else if (m.get(4) == Morpion.BLACK) count -= 0.2;
			if (m.get(6) == Morpion.WHITE) count++;
			else if (m.get(6) == Morpion.BLACK) count -= 0.2;
			
			if (count == 1) return 0.6;
		}
		
		return 0.1;
		
		
//		int ligne = 0;
//		double max=0;
//		if(pion_mis==0 || pion_mis==1 || pion_mis==2) {//1ere ligne
//			for (int i = 0; i < 3; i++) {
//				ligne += m.getVal(i);
//			}
//			if(val(ligne)>max) {
//				max = val(ligne);
//			}
//		}
//		ligne = 0;
//		if(pion_mis==3 || pion_mis==4 || pion_mis==5) {//2eme ligne
//			for (int i = 3; i < 6; i++) {
//				ligne += m.getVal(i);
//			}
//			if(val(ligne)>max) {
//				max = val(ligne);
//			}
//	    }
//		ligne = 0;
//		if(pion_mis==6 || pion_mis==7 || pion_mis==8) {//3eme ligne
//			for (int i = 6; i < 9; i++) {
//				ligne += m.getVal(i);
//			}
//			if(val(ligne)>max) {
//				max = val(ligne);
//			}
//	    }
//		ligne = 0;
//		if(pion_mis==0 || pion_mis==3 || pion_mis==6) {//1ere colonne
//			for (int i = 0; i < 7; i+=3) {
//				ligne += m.getVal(i);
//			}
//			if(val(ligne)>max) {
//				max = val(ligne);
//			}
//	    }
//		ligne = 0;
//		if(pion_mis==1 || pion_mis==4 || pion_mis==7) {//2eme colonne
//			for (int i = 1; i < 8; i+=3) {
//				ligne += m.getVal(i);
//			}
//			if(val(ligne)>max) {
//				max = val(ligne);
//			}
//	    }
//		ligne = 0;
//		if(pion_mis==2 || pion_mis==5 || pion_mis==8) {//3eme colonne
//			for (int i = 2; i < 9; i+=3) {
//				ligne += m.getVal(i);
//			}
//			if(val(ligne)>max) {
//				max = val(ligne);
//			}
//	    }
//		ligne = 0;
//		if(pion_mis==0 || pion_mis==4 || pion_mis==8) {//1ere diagonale
//			for (int i = 0; i < 9; i+=4) {
//				ligne += m.getVal(i);
//			}
//			if(val(ligne)>max) {
//				max = val(ligne);
//			}
//	    }
//		ligne = 0;
//		if(pion_mis==2 || pion_mis==4 || pion_mis==6) {//2eme diagonale
//			for (int i = 2; i < 7; i+=2) {
//				ligne += m.getVal(i);
//			}	
//			if(val(ligne)>max) {
//				max = val(ligne);
//			}
//			/*
//			 * 012
//			 * 345
//			 * 678
//			 */
//	    }
//
//	    return max;
	}
	
	public double val(int ligne) {
		if(ligne==3 || ligne==12) {
			return 1;
		}
		else if(color==Morpion.WHITE && ligne==9) {
			return 0.9;
		}
		else if(color==Morpion.BLACK && ligne==6) {
			return 0.9;
		}
		else if(color==Morpion.WHITE && ligne==2) {
			return 0.75;
		}
		else if(color==Morpion.BLACK && ligne==8) {
			return 0.75;
		}
		else {
			return 0;
		}
	}
	
	public void jouer(Morpion m){
		
		int c = play(m);
		while(c==-1)
		{
			c=play(m);
		}
		//System.out.println("Heuristique : "+heuristique(m, c));
		if (r != null) coups.add(new Coup(r.dump(), c, r.getOutput()[c]));
		//coups.add(new Coup(r.dump(), c, r.getOutput()[c]));
	}
	
	public void affiche_coups(ArrayList<Coup> p){
		for(int i=0;i<coups.size();i++){
			if(p.size()>i)
				System.out.println(coups.get(i)+" -> "+ p.get(i));
			else
				System.out.println(coups.get(i));

		}
	}
	
	public ArrayList<Coup> getCoups(){
		return coups;
	}
	
}
